package cc.shacocloud.mirage.restful;

import cc.shacocloud.mirage.restful.bind.BodyHandlerOptions;
import cc.shacocloud.mirage.restful.bind.SessionHandlerOptions;
import io.vertx.core.CompositeFuture;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServer;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.ext.web.handler.SessionHandler;
import io.vertx.ext.web.sstore.SessionStore;

import java.util.stream.Collectors;

/**
 * vertx 路由分发处理器，是框架的入口程序
 *
 * @see VertxRouterRequestMappingMappingRequestHandler
 * @see VertxRouterFilterMappingHandler
 */
public class VertxRouterDispatcherHandler {
    
    private final Vertx vertx;
    private final Router router;
    private final VertxRouterDispatcherOptions options;
    
    private VertxRouterDispatcherHandler(Vertx vertx, VertxRouterDispatcherOptions options) {
        this.vertx = vertx;
        this.router = Router.router(vertx);
        this.options = options;
    }
    
    /**
     * 简单的创建 httpServer 方法
     */
    public static Future<HttpServer> createHttpServer(Vertx vertx, VertxRouterDispatcherOptions options) {
        return new VertxRouterDispatcherHandler(vertx, options).createHttpServer();
    }
    
    /**
     * 构建http server
     */
    public Future<HttpServer> createHttpServer() {
        buildSessionHandler();
        buildBodyHandler();
        
        return CompositeFuture.all
                        (
                                options.getRouterMappingHandlers()
                                        .stream()
                                        .map(mh -> mh.bindRouterMapping(this.router))
                                        .collect(Collectors.toList())
                        )
                .compose(ar -> {
                    Promise<HttpServer> promise = Promise.promise();
                    vertx.createHttpServer(options.getServerOptions())
                            .requestHandler(router)
                            .listen(promise);
                    return promise.future();
                });
    }
    
    /**
     * 请求体处理器
     */
    private void buildBodyHandler() {
        BodyHandlerOptions bodyOptions = options.getBodyOptions();
        router.route().handler(
                BodyHandler.create()
                        .setHandleFileUploads(bodyOptions.isHandleFileUploads())
                        .setUploadsDirectory(bodyOptions.getUploadsDir())
                        .setBodyLimit(bodyOptions.getBodyLimit())
                        .setDeleteUploadedFilesOnEnd(bodyOptions.isDeleteUploadedFilesOnEnd())
                        .setMergeFormAttributes(bodyOptions.isMergeFormAttributes())
                        .setPreallocateBodyBuffer(bodyOptions.isPreallocateBodyBuffer())
        );
    }
    
    /**
     * 会话处理器
     */
    private void buildSessionHandler() {
        SessionHandlerOptions sessionOptions = options.getSessionOptions();
        router.route().handler(
                SessionHandler.create(SessionStore.create(vertx, JsonObject.mapFrom(sessionOptions.getStoreOptions())))
                        .setCookieHttpOnlyFlag(sessionOptions.isSessionCookieHttpOnly())
                        .setCookieSameSite(sessionOptions.getCookieSameSite())
                        .setCookieSecureFlag(sessionOptions.isSessionCookieSecure())
                        .setLazySession(sessionOptions.isLazySession())
                        .setMinLength(sessionOptions.getMinLength())
                        .setNagHttps(sessionOptions.isNagHttps())
                        .setSessionCookieName(sessionOptions.getSessionCookieName())
                        .setSessionCookiePath(sessionOptions.getSessionCookiePath())
                        .setSessionTimeout(sessionOptions.getSessionTimeout())
        );
    }
    
}
